package com.example.webchar.webchar.service.serverimpl;

import cn.hutool.core.bean.BeanUtil;
import com.example.webchar.webchar.novelenum.NovelStartEnum;
import com.example.webchar.webchar.model.Book;
import com.example.webchar.webchar.model.BookContent;
import com.example.webchar.webchar.model.BookMenu;
import com.example.webchar.webchar.pojo.Novel;
import com.example.webchar.webchar.service.CrawlService;
import lombok.extern.slf4j.Slf4j;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author 郭逍
 * @Date 2021/8/24 14:05
 */
@Slf4j
public class CrawTwoImpl implements CrawlService {

    private final String HTTP_HEAD = "https://www.bixiabook.com/";

    @Override
    public void novelCrawl(String name, String email) {
        Book book = loadBooks(name);

        /*
         * TODO 老毛有更好的思路, 没必要继续了 \<(^.^)>/
         * 1. 保存书本信息
         * 2. 获取书本id,
         * 3. 生成雪花id, 覆盖目录[id]吧值, 覆盖内容[章节id]值
         * 4. 批量插入目录, 批量插入内容
         * */
    }

    @Override
    public void novelCrawlChangeTheSource(String name) {

    }

    /**
     * name
     * 根据小说名, 获取小说目录, 小说内容
     */
    public Book loadBooks(String name) {
        Book book = null;

        try {
            // 获取小说详情页
            Map<String, String> bookDocument = getSearchLinksMap(name);
            // 将小说信息
            Document document = Jsoup.connect(bookDocument.get(name)).get();
            // 获取小说章节
            book = getNovel(document);

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            System.out.println(book);
        }
        return book;
    }


    /**
     * 获取小说详情页集合
     * <p>
     * 小说名 --- 小说文档对象
     *
     * @return - key: 小说名
     * - value: 小说详情页文档对象对于地址
     */
    private Map<String, String> getSearchLinksMap(String name) {
        Map<String, String> collect = null;

        try {
            Document novelSearchDoc = Jsoup.connect("https://www.bixiabook.com/index.php?s=/web/index/search").data("name", name).post();
            //返回爬取网站的信息
            Elements elementsByTag = novelSearchDoc.getElementById("main").getElementsByTag("li");
            //获取母模板
            // 解析li标签, 建立 [小说名/小说详情页地址]的map
            collect = elementsByTag.stream().skip(1).map(
                    li -> getBookDocument(li)).collect(Collectors.toMap(c -> c.getElementsByTag("meta").get(5).attr("content")
                    , li -> li.location()));
        } catch (IOException e) {
            log.error("根据{}请求小说详情页失败", name);
            e.printStackTrace();
        }
        return collect;
    }

    /**
     * 从文档中提取小说信息
     *
     * @param document 小说详情页文档对象
     * @return 小说对象
     */
    private Novel fillNovel(Document document) {
        if (document == null) {
            throw new RuntimeException("小说内容为空");
        }
        Elements novelElement = document.getElementsByTag("meta");
        //获取小说详情母版

        Novel novel = new Novel();
        novel.setName(novelElement.get(9).attr("content"));
        // todo 未设置小说更新地址(当前页面地址)
        novel.setUpdateLocation("");
        novel.setCompletionStatus(0);
        novel.setType(setNovelType(novelElement.get(8).attr("content")));
        novel.setUrl("https://www.bixiabook.com" + novelElement.get(7).attr("content"));
        novel.setScore(document.getElementById("score_content").getElementsByTag("em").get(0).text());
        novel.setBriefIntroduction(novelElement.get(6).attr("content"));
        novel.setNovelName(novelElement.get(5).attr("content"));
        novel.setCreateTime(new Date());
        novel.setUpdateTime(new Date());

        return novel;
    }

    /**
     * 从{@code <div id ="list"></div>}元素中, 获取小说章节列表
     *
     * @param doc 页面对象
     * @return - key 章节名
     * - value 小说地址
     */
    private Book getNovel(Document doc) {
        //获取目录页的信息
        Elements menuList = doc.getElementById("list").getElementsByTag("dd");

        HashMap<String, String> menus = new HashMap<>(642);
        for (Element element : menuList) {
            Elements a = element.getElementsByTag("a");
            String text = a.get(0).text();

            String href = HTTP_HEAD + a.attr("href");
            menus.put(text, href);
        }

        // 获取[章节/地址]列表
/*        Map<String, String> menus = menuList.stream().collect(Collectors.toMap(
                menu -> menu.getElementsByTag("a").get(0).text()
                , menu -> HTTP_HEAD + menu.getElementsByTag("a").get(0).attr("href")
        ));*/
        // 书本信息
        Book book = new Book();
        // 章节信息
        ArrayList<BookMenu> bookMenus = new ArrayList<>();
        // 获取内容
        menus.forEach((k, v) -> {
            try {
                Document contentDoc = Jsoup.connect(v).get();//获取详细内容
                // 获取内容部分
                Element contentElement = contentDoc.getElementById("content");
                // 删除开头p标签
                contentElement.getElementsByTag("p").get(0).remove();
                // 删除结尾div标签
                contentElement.getElementsByTag("div").remove();
                String content = contentElement.html();

                // 存储书本内容
                BookContent bookContent = new BookContent();
                bookContent.setContent(content);
                bookContent.setCreateTime(new Date());
                bookContent.setUpdateTime(new Date());

                // 存储书本目录
                BookMenu bookMenu = new BookMenu();
                bookMenu.setChapterName(k);
                bookMenu.setContent(bookContent);
                bookMenu.setCreateTime(new Date());
                bookMenu.setUpdateTime(new Date());
                // 添加书本章节信息
                bookMenus.add(bookMenu);

            } catch (IOException e) {
                e.printStackTrace();
            }
        });
        // 设置书本章节内容
        book.setBookMenus(bookMenus);

        // 通过小说详情页, 封装小说信息
        Novel novel = fillNovel(doc);

        BeanUtil.copyProperties(novel, book);

        return book;
    }

    /**
     * 获取li标签中第一个a连接, 并返回对应的页面对象
     *
     * @param li 小说li标签元素对象
     * @return 页面对象, 小说的详情页面
     */
    private Document getBookDocument(Element li) {
        Document chapterCon = null;
        //返回小说目录信息
        try {
            chapterCon = Jsoup.connect(HTTP_HEAD + li.getElementsByTag("a").get(0).attr("href")).get();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return chapterCon;
    }

    /**
     * 处理小说类型
     *
     * @param type 小说类型描述字符串
     * @return 类型对应值
     */
    private Integer setNovelType(String type) {
        Integer typeValue = 0;
        switch (type) {
            case "玄幻小说":
                typeValue = NovelStartEnum.FANTASY.ordinal();
                break;
            case "修真小说":
                typeValue = NovelStartEnum.FIXTHETRUTH.ordinal();
                break;
            case "都市小说":
                typeValue = NovelStartEnum.METROPOLIS.ordinal();
                break;
            case "穿越小说":
                typeValue = NovelStartEnum.THROUGH.ordinal();
                break;
            case "网游小说":
                typeValue = NovelStartEnum.ONLINE.ordinal();
                break;
            case "科幻小说":
                typeValue = NovelStartEnum.SCIENECFICTION.ordinal();
                break;
            default:
                typeValue = NovelStartEnum.OTHER.ordinal();
                break;
        }
        return typeValue;
    }

}
